import { BaseFlightInfo, FlightTime } from './../../interfaces/flight.interface';
import { HttpService } from '@nestjs/axios';
import { Injectable } from '@nestjs/common';
import { HtmlParseService } from '../html-parse/html-parse.service';
import { firstValueFrom } from 'rxjs';
import {
  FlightInfo,
  StateValues,
  TotalFlights,
} from 'src/flight/interfaces/flight.interface';
import { Cron } from '@nestjs/schedule';
import { prisma } from 'src/database';
import { TotalFlightsService } from '../total-flights/total-flights.service';
import { chooseTime } from 'src/utils/time-parse';

@Injectable()
export class FlightService {
  constructor(
    private readonly httpService: HttpService,
    private readonly htmlParseService: HtmlParseService,
    private readonly totalFlightsService: TotalFlightsService,
  ) { }

  // 路由测试用
  getTest(): string {
    return 'Flight Service Test';
  }

  //================================================获取航班数据===============================================
  // 获取页面状态值
  getStateValues = async (): Promise<StateValues> => {
    try {
      const response = await firstValueFrom(
        this.httpService.get('http://foc.ckair.com/FindinfoCrew.aspx'),
      );
      return this.htmlParseService.parseStateValues(response.data);
    } catch (error) {
      // 抛出错误：获取状态值失败！
      throw new Error('获取状态值失败！');
    }
  };

  // 按如期获取航班信息
  getFlightInfoByDate = async (date: string): Promise<FlightInfo[]> => {
    try {
      const stateValues: StateValues = await this.getStateValues();
      const params = {
        __VIEWSTATE: stateValues.viewState,
        __VIEWSTATEENCRYPTED: '',
        __EVENTVALIDATION: stateValues.viewEvent,
        TxtFlightDate: date,
        btQuery: '查询',
        cblFilter$0: 'on',
      };
      const response = await firstValueFrom(
        this.httpService.post(
          'http://foc.ckair.com/FindinfoCrew.aspx',
          params,
          {
            headers: {
              'Content-Type': 'application/x-www-form-urlencoded',
            },
          },
        ),
      );
      return this.htmlParseService.parseTable(response.data, date);
    } catch (error) {
      throw new Error('获取航班信息失败！');
    }
  };

  // // 按日计算航班量
  // totalFlightsCalculate(flights: FlightInfo[]): TotalFlights {
  //   flights.forEach((flight) => {
  //     const depTime = chooseTime({
  //       skdDepTime: flight.skdDepTime,
  //       estDepTime: flight.estDepTime,
  //       actDepTime: flight.actDepTime,
  //       skdArrTime: flight.skdArrTime,
  //       estArrTime: flight.estArrTime,
  //       actArrTime: flight.actArrTime,
  //     }, false)
  //   });
  // };

  // 为了便于统计当日浦东进港和出港的航班，获取连续三天的航班
  // 有装饰器的函数不能是箭头函数
  @Cron('0 * * * * *') // 每分钟执行一次
  async scheduledJob() {
    const currentDate: Date = new Date();
    const yesterday: Date = new Date(
      currentDate.getTime() - 24 * 60 * 60 * 1000,
    ); // 减去一天的毫秒数
    const tomorrow: Date = new Date(
      currentDate.getTime() + 24 * 60 * 60 * 1000,
    );
    // 构成字符串格式的日期列表
    const dateList: string[] = [
      yesterday.toISOString().slice(0, 10),
      currentDate.toISOString().slice(0, 10),
      tomorrow.toISOString().slice(0, 10),
    ];
    for (const date of dateList) {
      // 获取date日期的航班信息
      try {
        const response = await this.getFlightInfoByDate(date);
        await this.deleteAndInsertFlightsByDate(date, response);
        // 写入数据库
        await new Promise((resolve) => setTimeout(resolve, 1000)); // 延时1秒，避免频繁请求被ban
      } catch (error) {
        // 抛出错误：获取航班信息失败！
        throw new Error('获取航班信息失败！');
      }
    }
  }
  // ========================================================================================================

  // ================================================数据库操作===============================================
  // 插入一条航班信息
  async insertFlightInfo(flightInfo: FlightInfo): Promise<void> {
    try {
      // 插入航班信息
      await prisma.flightInfo.create({ data: flightInfo });
    } catch (error) {
      throw new Error('插入航班信息失败！');
    }
  }

  // 插入一组航班信息
  async insertFlightsList(flightInfoList: FlightInfo[]): Promise<void> {
    try {
      // 批量插入航班信息
      await prisma.flightInfo.createMany({ data: flightInfoList });
    } catch (error) {
      throw new Error('插入航班信息失败！');
    }
  }

  // 按id删除一条航班信息
  async deleteFlightById(id: string): Promise<void> {
    try {
      // 按id删除航班信息
      await prisma.flightInfo.delete({ where: { id } });
    } catch (error) {
      throw new Error('删除航班信息失败！');
    }
  }

  // 按日期批量删除航班信息
  async deleteFlightsByDate(date: string): Promise<void> {
    try {
      // 按日期删除航班信息
      await prisma.flightInfo.deleteMany({ where: { flightDate: date } });
    } catch (error) {
      throw new Error('删除航班信息失败！');
    }
  }

  // 更新一条航班信息
  async updateFlightById(id: string, flightInfo: FlightInfo): Promise<void> {
    try {
      // 按id更新航班信息
      await prisma.flightInfo.update({ where: { id }, data: flightInfo });
    } catch (error) {
      throw new Error('更新航班信息失败！');
    }
  }

  // 按id查询一条航班信息
  async queryFlightById(id: string): Promise<FlightInfo> {
    try {
      return await prisma.flightInfo.findUnique({ where: { id } });
    } catch (error) {
      throw new Error('查询航班信息失败！');
    }
  }

  // 按日期查询航班信息
  async queryFlightsByDate(date: string): Promise<FlightInfo[]> {
    try {
      return await prisma.flightInfo.findMany({ where: { flightDate: date } });
    } catch (error) {
      throw new Error('查询航班信息失败！');
    }
  }

  // 按日期和出发机场查询航班信息
  async queryFlightsByDepAirpot(
    date: string,
    airport: string,
  ): Promise<FlightInfo[]> {
    try {
      return await prisma.flightInfo.findMany({
        where: { flightDate: date, depAirport: airport },
      });
    } catch (error) {
      throw new Error('查询航班信息失败！');
    }
  }

  // 按日期和到达机场查询航班信息
  async queryFlightsByArrAirpot(
    date: string,
    airport: string,
  ): Promise<FlightInfo[]> {
    try {
      return await prisma.flightInfo.findMany({
        where: { flightDate: date, arrAirport: airport },
      });
    } catch (error) {
      throw new Error('查询航班信息失败！');
    }
  }

  // 按日期删除并写入新的数据，通过事务的方式实现
  async deleteAndInsertFlightsByDate(
    date: string,
    flightInfoList: FlightInfo[],
  ) {
    try {
      // 删除并写入新的数据
      await prisma.$transaction([
        prisma.flightInfo.deleteMany({ where: { flightDate: date } }),
        prisma.flightInfo.createMany({ data: flightInfoList }),
      ]);
    } catch (error) {
      throw new Error('操作失败！');
    }
  }

  // 生成指定日期浦东机场的航班信息列表
  async generateBaseFlightsInfoList(date: string): Promise<BaseFlightInfo[]> {
    const aircraftList: string[] = ['2077', '2076', '220E', '220F', '221S', '221W', '222H', '222J', '222K', '222N', '222V', '222Z', '223A', '223F']
    // const baseFlightInfo: BaseFlightInfo = {
    //   regNo: '',
    //   type: '',
    //   flightDate: new Date(date),
    //   preFlightNo: '',
    //   depAirport: '浦东',
    //   arrTime: null,
    //   depTime: null,
    //   nextFlightNo: '',
    //   arrAirport: '',
    // };
    const baseFlights: BaseFlightInfo[] = [];
    // 生成相邻3天的日期列表
    const today: Date = new Date(date);
    const yesterday: Date = new Date(
      today.getTime() - 24 * 60 * 60 * 1000,
    ); // 减去一天的毫秒数
    // 构成字符串格式的日期列表
    const dateList: string[] = [
      yesterday.toISOString().slice(0, 10),
      today.toISOString().slice(0, 10),
    ];
    const arrFlightInfos: FlightInfo[] = [];
    const depFlightInfos: FlightInfo[] = []
    for (const currentDate of dateList) {
      try {
        // 查询该日期浦东机场的航班信息
        const arrFlights: FlightInfo[] = await this.queryFlightsByArrAirpot(
          currentDate,
          '浦东',
        );
        const depFlights: FlightInfo[] = await this.queryFlightsByDepAirpot(
          currentDate,
          '浦东',
        );
        // 将arrFlights和depFlights合并到arrFlightInfos和depFlightInfos中
        arrFlightInfos.push(...arrFlights); // 使用扩展运算符将数组元素展开
        depFlightInfos.push(...depFlights);
      } catch (error) {
        throw new Error('查询航班信息失败！');
      }
    }
    console.log(arrFlightInfos);
    return baseFlights;
  }


}
